added Feb 2001 SDK
[windows-sources.git] / shared source / sscli20 / jscript / engine / vsaengine.cs
blobe1dacd3f41e064abaa762ff241323f1b1743b470
1 // ==++==
2 //
3 //
4 // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
5 //
6 // The use and distribution terms for this software are contained in the file
7 // named license.txt, which can be found in the root of this distribution.
8 // By using this software in any fashion, you are agreeing to be bound by the
9 // terms of this license.
10 //
11 // You must not remove this notice, or any other, from this software.
12 //
13 //
14 // ==--==
16 namespace Microsoft.JScript.Vsa{
18 using Microsoft.JScript;
19 using Microsoft.Vsa;
20 using System;
21 using System.Collections;
22 using System.IO;
23 using System.Globalization;
24 using System.Reflection;
25 using System.Reflection.Emit;
26 using System.Resources;
27 using System.Text;
28 using System.Threading;
29 using System.Xml;
30 using System.Runtime.Remoting.Messaging;
31 using System.Security;
32 using System.Security.Cryptography;
33 using System.Security.Permissions;
34 using System.Runtime.InteropServices;
37 internal enum LoaderAPI {
38 LoadFrom,
39 LoadFile,
40 ReflectionOnlyLoadFrom
44 [GuidAttribute("B71E484D-93ED-4b56-BFB9-CEED5134822B")]
45 [ComVisible(true)]
46 [Obsolete(VsaObsolete.Description)]
47 public sealed class VsaEngine : BaseVsaEngine, IEngine2, IRedirectOutput{
48 internal bool alwaysGenerateIL;
49 private bool autoRef;
50 private Hashtable Defines;
51 internal bool doCRS;
52 internal bool doFast;
53 internal bool doPrint;
54 internal bool doSaveAfterCompile;
55 private bool doWarnAsError;
56 private int nWarningLevel;
57 internal bool genStartupClass;
58 internal bool isCLSCompliant;
59 internal bool versionSafe;
60 private String PEFileName;
61 internal PEFileKinds PEFileKind;
62 internal PortableExecutableKinds PEKindFlags;
63 internal ImageFileMachine PEMachineArchitecture;
64 internal LoaderAPI ReferenceLoaderAPI;
65 private Version versionInfo;
67 private CultureInfo errorCultureInfo;
70 //In appdomain used to executing JScript debugger expression evaluator
71 static internal bool executeForJSEE = false;
73 private String libpath;
74 private String[] libpathList;
76 private bool isCompilerSet;
78 internal VsaScriptScope globalScope;
79 private ArrayList packages;
80 private ArrayList scopes;
81 private ArrayList implicitAssemblies;
82 private SimpleHashtable implicitAssemblyCache;
83 private ICollection managedResources;
84 private string debugDirectory;
85 private string tempDirectory;
86 private RNGCryptoServiceProvider randomNumberGenerator;
87 private byte[] rawPE;
88 private byte[] rawPDB;
89 internal int classCounter;
91 private SimpleHashtable cachedTypeLookups;
93 internal Thread runningThread;
94 private CompilerGlobals compilerGlobals;
95 private Globals globals;
97 // Used only during VsaEngine.Compile. It is reset at the beginning of the
98 // function. It is incremented as errors are reported via OnCompilerError.
99 private int numberOfErrors;
101 private String runtimeDirectory;
102 private static readonly Version CurrentProjectVersion = new Version("1.0");
104 private Hashtable typenameTable; // for checking CLS compliance
106 private static string engineVersion = GetVersionString();
107 private static string GetVersionString(){
108 return BuildVersionInfo.MajorVersion
109 + "." + BuildVersionInfo.MinorVersion.ToString(CultureInfo.InvariantCulture).PadLeft(2, '0')
110 + "." + BuildVersionInfo.Revision.ToString(CultureInfo.InvariantCulture)
111 + "." + BuildVersionInfo.Build.ToString(CultureInfo.InvariantCulture).PadLeft(4, '0');
115 public VsaEngine()
116 :this(true){
119 public VsaEngine(bool fast) : base("JScript", VsaEngine.engineVersion, true){
120 this.alwaysGenerateIL = false;
121 this.autoRef = false;
122 this.doCRS = false;
123 this.doFast = fast;
124 this.genDebugInfo = false;
125 this.genStartupClass = true;
126 this.doPrint = false;
127 this.doWarnAsError = false;
128 this.nWarningLevel = 4;
129 this.isCLSCompliant = false;
130 this.versionSafe = false;
131 this.PEFileName = null;
132 this.PEFileKind = PEFileKinds.Dll;
133 this.PEKindFlags = PortableExecutableKinds.ILOnly;
134 this.PEMachineArchitecture = ImageFileMachine.I386;
135 this.ReferenceLoaderAPI = LoaderAPI.LoadFrom;
136 this.errorCultureInfo = null;
137 this.libpath = null;
138 this.libpathList = null;
140 this.globalScope = null;
141 this.vsaItems = new VsaItems(this);
142 this.packages = null;
143 this.scopes = null;
144 this.classCounter = 0;
145 this.implicitAssemblies = null;
146 this.implicitAssemblyCache = null;
147 this.cachedTypeLookups = null;
149 this.isEngineRunning = false;
150 this.isEngineCompiled = false;
151 this.isCompilerSet = false;
152 this.isClosed = false;
154 this.runningThread = null;
155 this.compilerGlobals = null;
156 this.globals = null;
157 this.runtimeDirectory = null;
158 Globals.contextEngine = this;
159 this.runtimeAssembly = null;
160 this.typenameTable = null;
163 private Assembly runtimeAssembly;
164 private static Hashtable assemblyReferencesTable = null;
165 // This constructor is called at run time to instantiate an engine for a given assembly
166 private VsaEngine(Assembly runtimeAssembly) : this(true){
167 this.runtimeAssembly = runtimeAssembly;
170 private static Module reflectionOnlyVsaModule = null;
171 private static Module reflectionOnlyJScriptModule = null;
173 internal void EnsureReflectionOnlyModulesLoaded() {
174 if (VsaEngine.reflectionOnlyVsaModule == null) {
175 VsaEngine.reflectionOnlyVsaModule = Assembly.ReflectionOnlyLoadFrom(typeof(IVsaEngine).Assembly.Location).GetModule("Microsoft.Vsa.dll");
176 VsaEngine.reflectionOnlyJScriptModule = Assembly.ReflectionOnlyLoadFrom(typeof(VsaEngine).Assembly.Location).GetModule("Microsoft.JScript.dll");
180 internal Module VsaModule {
181 get {
182 if (this.ReferenceLoaderAPI != LoaderAPI.ReflectionOnlyLoadFrom)
183 return typeof(IVsaEngine).Module;
184 EnsureReflectionOnlyModulesLoaded();
185 return VsaEngine.reflectionOnlyVsaModule;
189 internal Module JScriptModule {
190 get {
191 if (this.ReferenceLoaderAPI != LoaderAPI.ReflectionOnlyLoadFrom)
192 return typeof(VsaEngine).Module;
193 EnsureReflectionOnlyModulesLoaded();
194 return VsaEngine.reflectionOnlyJScriptModule;
198 private void AddChildAndValue(XmlDocument doc, XmlElement parent, string name, string value){
199 XmlElement option = doc.CreateElement(name);
200 this.CreateAttribute(doc, option, "Value", value);
201 parent.AppendChild(option);
204 internal void AddPackage(PackageScope pscope){
205 if (this.packages == null)
206 this.packages = new ArrayList(8);
207 IEnumerator e = this.packages.GetEnumerator();
208 while (e.MoveNext()){
209 PackageScope cps = (PackageScope)e.Current;
210 if (cps.name.Equals(pscope.name)){
211 cps.owner.MergeWith(pscope.owner);
212 return;
215 this.packages.Add(pscope);
218 internal void CheckForErrors(){
219 if (!this.isClosed && !this.isEngineCompiled){
220 SetUpCompilerEnvironment();
221 Globals.ScopeStack.Push(this.GetGlobalScope().GetObject());
222 try{
223 foreach (Object item in this.vsaItems){
224 if (item is VsaReference)
225 ((VsaReference)item).Compile(); //Load the assembly into memory.
227 if (this.vsaItems.Count > 0)
228 this.SetEnclosingContext(new WrappedNamespace("", this)); //Provide a way to find types that are not inside of a name space
229 foreach (Object item in this.vsaItems){
230 if (!(item is VsaReference))
231 ((VsaItem)item).CheckForErrors();
233 if (null != this.globalScope)
234 this.globalScope.CheckForErrors(); //In case the host added items to the global scope.
235 }finally{
236 Globals.ScopeStack.Pop();
239 this.globalScope = null;
242 [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
243 public IVsaEngine Clone(AppDomain domain){
244 throw new NotImplementedException();
247 // See security comment at BaseVsa.Run()
248 [PermissionSet(SecurityAction.Demand, Name="FullTrust")]
249 public bool CompileEmpty(){
250 this.TryObtainLock();
251 try{
252 return this.DoCompile();
253 }finally{
254 this.ReleaseLock();
258 private void CreateAttribute(XmlDocument doc, XmlElement elem, string name, string value){
259 XmlAttribute attribute = doc.CreateAttribute(name);
260 elem.SetAttributeNode(attribute);
261 elem.SetAttribute(name, value);
264 [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
265 public void ConnectEvents(){
268 internal CompilerGlobals CompilerGlobals{
269 get{
270 if (this.compilerGlobals == null)
271 this.compilerGlobals = new CompilerGlobals(this, this.Name, this.PEFileName, this.PEFileKind,
272 this.doSaveAfterCompile || this.genStartupClass, !this.doSaveAfterCompile || this.genStartupClass, this.genDebugInfo, this.isCLSCompliant,
273 this.versionInfo, this.globals);
274 return this.compilerGlobals;
279 private static TypeReferences _reflectionOnlyTypeRefs;
280 private TypeReferences TypeRefs {
281 get {
282 TypeReferences typeRefs;
283 if (LoaderAPI.ReflectionOnlyLoadFrom == this.ReferenceLoaderAPI) {
284 typeRefs = VsaEngine._reflectionOnlyTypeRefs;
285 if (null == typeRefs)
286 typeRefs = VsaEngine._reflectionOnlyTypeRefs = new TypeReferences(this.JScriptModule);
287 } else
288 typeRefs = Runtime.TypeRefs;
289 return typeRefs;
293 public static GlobalScope CreateEngineAndGetGlobalScope(bool fast, String[] assemblyNames){
294 VsaEngine engine = new VsaEngine(fast);
295 engine.InitVsaEngine("JScript.Vsa.VsaEngine://Microsoft.JScript.VsaEngine.Vsa", new DefaultVsaSite());
296 engine.doPrint = true;
297 engine.SetEnclosingContext(new WrappedNamespace("", engine));
298 foreach (String assemblyName in assemblyNames){
299 VsaReference r = (VsaReference)engine.vsaItems.CreateItem(assemblyName, VsaItemType.Reference, VsaItemFlag.None);
300 r.AssemblyName = assemblyName;
302 VsaEngine.exeEngine = engine;
303 GlobalScope scope = (GlobalScope)engine.GetGlobalScope().GetObject();
304 scope.globalObject = engine.Globals.globalObject;
305 return scope;
308 public static GlobalScope CreateEngineAndGetGlobalScopeWithType(bool fast, String[] assemblyNames, RuntimeTypeHandle callingTypeHandle){
309 return VsaEngine.CreateEngineAndGetGlobalScopeWithTypeAndRootNamespace(fast, assemblyNames, callingTypeHandle, null);
312 public static GlobalScope CreateEngineAndGetGlobalScopeWithTypeAndRootNamespace(bool fast, String[] assemblyNames, RuntimeTypeHandle callingTypeHandle, string rootNamespace){
313 VsaEngine engine = new VsaEngine(fast);
314 engine.InitVsaEngine("JScript.Vsa.VsaEngine://Microsoft.JScript.VsaEngine.Vsa", new DefaultVsaSite());
315 engine.doPrint = true;
316 engine.SetEnclosingContext(new WrappedNamespace("", engine));
317 if (rootNamespace != null)
318 engine.SetEnclosingContext(new WrappedNamespace(rootNamespace, engine));
320 foreach (String assemblyName in assemblyNames){
321 VsaReference r = (VsaReference)engine.vsaItems.CreateItem(assemblyName, VsaItemType.Reference, VsaItemFlag.None);
322 r.AssemblyName = assemblyName;
324 // Put the engine in the CallContext so that calls to CreateEngineWithType will return this engine
325 Type callingType = Type.GetTypeFromHandle(callingTypeHandle);
326 Assembly callingAssembly = callingType.Assembly;
327 System.Runtime.Remoting.Messaging.CallContext.SetData("JScript:" + callingAssembly.FullName, engine);
328 // Get and return the global scope
329 GlobalScope scope = (GlobalScope)engine.GetGlobalScope().GetObject();
330 scope.globalObject = engine.Globals.globalObject;
331 return scope;
334 private static volatile VsaEngine exeEngine; // Instance of VsaEngine used by JScript EXEs
336 // This factory method is called by EXE code only
337 public static VsaEngine CreateEngine(){
338 if (VsaEngine.exeEngine == null){
339 VsaEngine e = new VsaEngine(true);
340 e.InitVsaEngine("JScript.Vsa.VsaEngine://Microsoft.JScript.VsaEngine.Vsa", new DefaultVsaSite());
341 VsaEngine.exeEngine = e;
343 return VsaEngine.exeEngine;
346 internal static VsaEngine CreateEngineForDebugger(){
347 VsaEngine engine = new VsaEngine(true);
348 engine.InitVsaEngine("JScript.Vsa.VsaEngine://Microsoft.JScript.VsaEngine.Vsa", new DefaultVsaSite());
349 GlobalScope scope = (GlobalScope)engine.GetGlobalScope().GetObject();
350 scope.globalObject = engine.Globals.globalObject;
351 return engine;
354 // This factory method is called by DLL code only
355 public static VsaEngine CreateEngineWithType(RuntimeTypeHandle callingTypeHandle){
356 Type callingType = Type.GetTypeFromHandle(callingTypeHandle);
357 Assembly callingAssembly = callingType.Assembly;
358 Object o = System.Runtime.Remoting.Messaging.CallContext.GetData("JScript:" + callingAssembly.FullName);
359 if (o != null){
360 VsaEngine e = o as VsaEngine;
361 if (e != null)
362 return e;
365 VsaEngine engine = new VsaEngine(callingAssembly);
366 engine.InitVsaEngine("JScript.Vsa.VsaEngine://Microsoft.JScript.VsaEngine.Vsa", new DefaultVsaSite());
368 GlobalScope scope = (GlobalScope)engine.GetGlobalScope().GetObject();
369 scope.globalObject = engine.Globals.globalObject;
371 // for every global class generated in this assembly make an instance and call the global code method
372 int i = 0;
373 Type globalClassType = null;
375 String globalClassName = "JScript " + i.ToString(CultureInfo.InvariantCulture);
376 globalClassType = callingAssembly.GetType(globalClassName, false);
377 if (globalClassType != null){
378 engine.SetEnclosingContext(new WrappedNamespace("", engine));
379 ConstructorInfo globalScopeConstructor = globalClassType.GetConstructor(new Type[]{typeof(GlobalScope)});
380 MethodInfo globalCode = globalClassType.GetMethod("Global Code");
381 try{
382 Object globalClassInstance = globalScopeConstructor.Invoke(new Object[]{scope});
383 globalCode.Invoke(globalClassInstance, new Object[0]);
384 }catch(SecurityException){
385 // [stesty] Due to bug 337909, if a JScript assembly is strongly-named but partially-trusted, it will
386 // not succeed here unless it also has the AllowPartiallyTrustedCallersAttribute. We do not
387 // want to run this constructor with elevated permissions, so we work around by abandoning
388 // the attempt, thus disabling eval in this scenario.
389 break;
392 i++;
393 }while (globalClassType != null);
395 if (o == null)
396 System.Runtime.Remoting.Messaging.CallContext.SetData("JScript:" + callingAssembly.FullName, engine);
397 return engine;
400 private void AddReferences(){
401 if (VsaEngine.assemblyReferencesTable == null) {
402 // Create the cache
403 Hashtable h = new Hashtable();
404 VsaEngine.assemblyReferencesTable = Hashtable.Synchronized(h);
407 String[] references = VsaEngine.assemblyReferencesTable[this.runtimeAssembly.FullName] as String[];
408 if (references != null){
409 for (int i = 0; i < references.Length; i++){
410 VsaReference r = (VsaReference)this.vsaItems.CreateItem(references[i], VsaItemType.Reference, VsaItemFlag.None);
411 r.AssemblyName = references[i];
413 }else{
414 // Read the references from the custom attribute on the assembly and create VsaReferences for each
415 // of them.
416 Object[] attrs = CustomAttribute.GetCustomAttributes(this.runtimeAssembly, typeof(ReferenceAttribute), false);
417 String[] references1 = new String[attrs.Length];
418 for (int i = 0; i < attrs.Length; i++){
419 String assemblyName = ((ReferenceAttribute)attrs[i]).reference;
420 VsaReference r = (VsaReference)this.vsaItems.CreateItem(assemblyName, VsaItemType.Reference, VsaItemFlag.None);
421 r.AssemblyName = assemblyName;
422 references1[i] = assemblyName;
424 VsaEngine.assemblyReferencesTable[this.runtimeAssembly.FullName] = references1;
428 private void EmitReferences()
430 SimpleHashtable emitted = new SimpleHashtable((uint)this.vsaItems.Count + (this.implicitAssemblies == null ? 0 : (uint)this.implicitAssemblies.Count));
431 foreach (Object item in this.vsaItems){
432 if (item is VsaReference){
433 String referenceName = ((VsaReference)item).Assembly.GetName().FullName;
434 // do not write duplicate assemblies
435 if (emitted[referenceName] == null){
436 CustomAttributeBuilder cab = new CustomAttributeBuilder(CompilerGlobals.referenceAttributeConstructor, new Object[1] {referenceName});
437 this.CompilerGlobals.assemblyBuilder.SetCustomAttribute(cab);
438 emitted[referenceName] = item;
442 if (this.implicitAssemblies != null){
443 foreach (Object item in this.implicitAssemblies){
444 Assembly a = item as Assembly;
445 if (a != null){
446 String referenceName = a.GetName().FullName;
447 // do not write duplicate assemblies
448 if (emitted[referenceName] == null){
449 CustomAttributeBuilder cab = new CustomAttributeBuilder(CompilerGlobals.referenceAttributeConstructor, new Object[1] {referenceName});
450 this.CompilerGlobals.assemblyBuilder.SetCustomAttribute(cab);
451 emitted[referenceName] = item;
458 private void CreateMain(){
459 // define a class that will hold the main method
460 TypeBuilder mainClass = this.CompilerGlobals.module.DefineType("JScript Main", TypeAttributes.Public);
462 // create a function with the following signature void Main(String[] args)
463 MethodBuilder main = mainClass.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static, Typeob.Void, new Type[]{Typeob.ArrayOfString});
464 ILGenerator il = main.GetILGenerator();
466 // emit code for main method
467 this.CreateEntryPointIL(il, null /* site */);
469 // cook method and class
470 mainClass.CreateType();
471 // define the Main() method as the entry point for the exe
472 this.CompilerGlobals.assemblyBuilder.SetEntryPoint(main, this.PEFileKind);
475 private void CreateStartupClass(){
476 // define _Startup class for VSA (in the RootNamespace)
477 Debug.Assert(this.rootNamespace != null && this.rootNamespace.Length > 0);
478 TypeBuilder startupClass = this.CompilerGlobals.module.DefineType(this.rootNamespace + "._Startup", TypeAttributes.Public, Typeob.BaseVsaStartup);
479 FieldInfo site = Typeob.BaseVsaStartup.GetField("site", BindingFlags.NonPublic | BindingFlags.Instance);
480 // create a function with the following signature: public virtual void Startup()
481 MethodBuilder startup = startupClass.DefineMethod("Startup", MethodAttributes.Public | MethodAttributes.Virtual, Typeob.Void, Type.EmptyTypes);
482 this.CreateEntryPointIL(startup.GetILGenerator(), site, startupClass);
483 // create a function with the following signature: public virtual void Shutdown()
484 MethodBuilder shutdown = startupClass.DefineMethod("Shutdown", MethodAttributes.Public | MethodAttributes.Virtual, Typeob.Void, Type.EmptyTypes);
485 this.CreateShutdownIL(shutdown.GetILGenerator());
487 // cook method and class
488 startupClass.CreateType();
491 void CreateEntryPointIL(ILGenerator il, FieldInfo site){
492 this.CreateEntryPointIL(il, site, null);
495 void CreateEntryPointIL(ILGenerator il, FieldInfo site, TypeBuilder startupClass){
496 LocalBuilder globalScope = il.DeclareLocal(Typeob.GlobalScope);
498 //Emit code to create an engine. We do this explicitly so that we can control fast mode.
499 if (this.doFast)
500 il.Emit(OpCodes.Ldc_I4_1);
501 else
502 il.Emit(OpCodes.Ldc_I4_0);
503 //Run through the list of references and emit code to create an array of strings representing them
504 //but do not emit duplicates.
505 SimpleHashtable uniqueReferences = new SimpleHashtable((uint)this.vsaItems.Count);
506 ArrayList references = new ArrayList();
507 foreach (Object item in this.vsaItems){
508 if (item is VsaReference){
509 string assemblyName = ((VsaReference)item).Assembly.GetName().FullName;
510 if (uniqueReferences[assemblyName] == null){
511 references.Add(assemblyName);
512 uniqueReferences[assemblyName] = item;
516 if (this.implicitAssemblies != null){
517 foreach (Object item in this.implicitAssemblies){
518 Assembly a = item as Assembly;
519 if (a != null){
520 String assemblyName = a.GetName().FullName;
521 if (uniqueReferences[assemblyName] == null){
522 references.Add(assemblyName);
523 uniqueReferences[assemblyName] = item;
529 ConstantWrapper.TranslateToILInt(il, references.Count);
530 il.Emit(OpCodes.Newarr, Typeob.String);
531 int num = 0;
532 foreach (string referenceName in references){
533 il.Emit(OpCodes.Dup);
534 ConstantWrapper.TranslateToILInt(il, num++);
535 il.Emit(OpCodes.Ldstr, referenceName);
536 il.Emit(OpCodes.Stelem_Ref);
538 if (startupClass != null){
539 il.Emit(OpCodes.Ldtoken, startupClass);
540 if (this.rootNamespace != null)
541 il.Emit(OpCodes.Ldstr, this.rootNamespace);
542 else
543 il.Emit(OpCodes.Ldnull);
544 MethodInfo createEngineAndGetGlobalScopeWithTypeAndRootNamespace = Typeob.VsaEngine.GetMethod("CreateEngineAndGetGlobalScopeWithTypeAndRootNamespace");
545 il.Emit(OpCodes.Call, createEngineAndGetGlobalScopeWithTypeAndRootNamespace);
546 }else{
547 MethodInfo createEngineAndGetGlobalScope = Typeob.VsaEngine.GetMethod("CreateEngineAndGetGlobalScope");
548 il.Emit(OpCodes.Call, createEngineAndGetGlobalScope);
550 il.Emit(OpCodes.Stloc, globalScope);
552 // get global object instances and event source instances (CreateStartupClass scenario only)
553 if (site != null) this.CreateHostCallbackIL(il, site);
555 bool setUserEntryPoint = this.genDebugInfo;
557 // for every generated class make an instance and call the main routine method
559 // When there are multiple VsaStaticCode items, all members of relevance are lifted to the
560 // first one. VsaStaticCode does not munge with the runtime scope chain, and instead
561 // relies on the code here to set things up before the global code is called.
562 bool codeToSetupGlobalScopeEmitted = false; // have we hit the first VsaStaticCode item
563 foreach (Object item in this.vsaItems){
564 Type compiledType = ((VsaItem)item).GetCompiledType();
565 if (null != compiledType){
566 ConstructorInfo globalScopeConstructor = compiledType.GetConstructor(new Type[]{Typeob.GlobalScope});
567 MethodInfo globalCode = compiledType.GetMethod("Global Code");
568 if (setUserEntryPoint){
569 //Set the Global Code method of the first code item to be the place where the debugger breaks for the first step into
570 this.CompilerGlobals.module.SetUserEntryPoint(globalCode);
571 setUserEntryPoint = false; //Do it once only
574 il.Emit(OpCodes.Ldloc, globalScope);
575 il.Emit(OpCodes.Newobj, globalScopeConstructor);
577 if (!codeToSetupGlobalScopeEmitted && item is VsaStaticCode) {
578 // This is the first VsaStaticCode item which holds all the relevant members.
579 // Push it onto the runtime scope stack.
580 LocalBuilder firstStaticScope = il.DeclareLocal(compiledType); // all members lifted to this object
581 il.Emit(OpCodes.Stloc, firstStaticScope);
583 // Call globalScope.engine.PushScriptObject(firstStaticScope)
584 il.Emit(OpCodes.Ldloc, globalScope);
585 il.Emit(OpCodes.Ldfld, CompilerGlobals.engineField);
586 il.Emit(OpCodes.Ldloc, firstStaticScope);
587 il.Emit(OpCodes.Call, CompilerGlobals.pushScriptObjectMethod);
589 // Restore stack for the next Call instruction.
590 il.Emit(OpCodes.Ldloc, firstStaticScope);
591 codeToSetupGlobalScopeEmitted = true;
594 il.Emit(OpCodes.Call, globalCode);
595 il.Emit(OpCodes.Pop);
599 if (codeToSetupGlobalScopeEmitted) {
600 // A VsaStaticCode item was encountered and code to setup the runtime
601 // stack was emitted. Restore the stack.
602 il.Emit(OpCodes.Ldloc, globalScope);
603 il.Emit(OpCodes.Ldfld, CompilerGlobals.engineField);
604 il.Emit(OpCodes.Call, CompilerGlobals.popScriptObjectMethod);
605 il.Emit(OpCodes.Pop);
608 // a method needs a return opcode
609 il.Emit(OpCodes.Ret);
612 private void CreateHostCallbackIL(ILGenerator il, FieldInfo site){
613 // Do callbacks to the host for global object instances
614 MethodInfo getGlobalInstance = site.FieldType.GetMethod("GetGlobalInstance");
615 MethodInfo getEventSourceInstance = site.FieldType.GetMethod("GetEventSourceInstance");
616 foreach (Object item in this.vsaItems){
617 if (item is VsaHostObject){
618 VsaHostObject hostObject = (VsaHostObject)item;
619 // get global item instance from site
620 il.Emit(OpCodes.Ldarg_0);
621 il.Emit(OpCodes.Ldfld, site);
622 il.Emit(OpCodes.Ldstr, hostObject.Name);
623 il.Emit(OpCodes.Callvirt, getGlobalInstance);
624 // cast instance to the correct type and store into the global field
625 Type target_type = hostObject.Field.FieldType;
626 il.Emit(OpCodes.Ldtoken, target_type);
627 il.Emit(OpCodes.Call, CompilerGlobals.getTypeFromHandleMethod);
628 ConstantWrapper.TranslateToILInt(il, 0);
629 il.Emit(OpCodes.Call, CompilerGlobals.coerceTMethod);
630 if (target_type.IsValueType)
631 Microsoft.JScript.Convert.EmitUnbox(il, target_type, Type.GetTypeCode(target_type));
632 else
633 il.Emit(OpCodes.Castclass, target_type);
634 il.Emit(OpCodes.Stsfld, hostObject.Field);
639 private void CreateShutdownIL(ILGenerator il){
640 // release references to global instances
641 foreach (Object item in this.vsaItems){
642 if (item is VsaHostObject){
643 il.Emit(OpCodes.Ldnull);
644 il.Emit(OpCodes.Stsfld, ((VsaHostObject)item).Field);
647 il.Emit(OpCodes.Ret);
650 [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
651 public void DisconnectEvents(){
654 protected override void DoClose(){
655 ((VsaItems)this.vsaItems).Close();
656 if (null != this.globalScope)
657 this.globalScope.Close();
658 this.vsaItems = null;
659 this.engineSite = null;
660 this.globalScope = null;
661 this.runningThread = null;
662 this.compilerGlobals = null;
663 this.globals = null;
664 ScriptStream.Out = Console.Out;
665 ScriptStream.Error = Console.Error;
666 this.rawPE = null;
667 this.rawPDB = null;
668 this.isClosed = true;
669 if (this.tempDirectory != null && Directory.Exists(this.tempDirectory))
670 Directory.Delete(this.tempDirectory);
673 protected override bool DoCompile(){
674 if (!this.isClosed && !this.isEngineCompiled){
675 this.SetUpCompilerEnvironment();
676 if (this.PEFileName == null){
677 // we use random default names to avoid overwriting cached assembly files when debugging VSA
678 this.PEFileName = this.GenerateRandomPEFileName();
680 this.SaveSourceForDebugging(); // Save sources needed for debugging (does nothing if no debug info)
681 this.numberOfErrors = 0; // Records number of errors during compilation.
682 this.isEngineCompiled = true; // OnCompilerError sets to false if it encounters an unrecoverable error.
683 Globals.ScopeStack.Push(this.GetGlobalScope().GetObject());
684 try{
685 try{
686 foreach (Object item in this.vsaItems){
687 Debug.Assert(item is VsaReference || item is VsaStaticCode || item is VsaHostObject);
688 if (item is VsaReference)
689 ((VsaReference)item).Compile(); //Load the assembly into memory.
691 if (this.vsaItems.Count > 0)
692 this.SetEnclosingContext(new WrappedNamespace("", this)); //Provide a way to find types that are not inside of a name space
693 // Add VSA global items to the global scope
694 foreach (Object item in this.vsaItems){
695 if (item is VsaHostObject)
696 ((VsaHostObject)item).Compile();
698 foreach (Object item in this.vsaItems){
699 if (item is VsaStaticCode)
700 ((VsaStaticCode)item).Parse();
702 foreach (Object item in this.vsaItems){
703 if (item is VsaStaticCode)
704 ((VsaStaticCode)item).ProcessAssemblyAttributeLists();
706 foreach (Object item in this.vsaItems){
707 if (item is VsaStaticCode)
708 ((VsaStaticCode)item).PartiallyEvaluate();
710 foreach (Object item in this.vsaItems){
711 if (item is VsaStaticCode)
712 ((VsaStaticCode)item).TranslateToIL();
714 foreach (Object item in this.vsaItems){
715 if (item is VsaStaticCode)
716 ((VsaStaticCode)item).GetCompiledType();
718 if (null != this.globalScope)
719 this.globalScope.Compile(); //In case the host added items to the global scope
720 }catch(JScriptException se){
721 // It's a bit strange because we may be capturing an exception
722 // thrown by VsaEngine.OnCompilerError (in the case where
723 // this.engineSite is null. This is fine though. All we end up doing
724 // is capturing and then rethrowing the same error.
725 this.OnCompilerError(se);
726 }catch(System.IO.FileLoadException e){
727 JScriptException se = new JScriptException(JSError.ImplicitlyReferencedAssemblyNotFound);
728 se.value = e.FileName;
729 this.OnCompilerError(se);
730 this.isEngineCompiled = false;
731 }catch(EndOfFile){
732 // an error was reported during PartiallyEvaluate and the host decided to abort
733 // swallow the exception and keep going
734 }catch{
735 // internal compiler error -- make sure we don't claim to have compiled, then rethrow
736 this.isEngineCompiled = false;
737 throw;
739 }finally{
740 Globals.ScopeStack.Pop();
742 if (this.isEngineCompiled){
743 // there were no unrecoverable errors, but we want to return true only if there is IL
744 this.isEngineCompiled = (this.numberOfErrors == 0 || this.alwaysGenerateIL);
749 if (this.managedResources != null){
750 foreach (ResInfo managedResource in this.managedResources){
751 if (managedResource.isLinked){
752 this.CompilerGlobals.assemblyBuilder.AddResourceFile(managedResource.name,
753 Path.GetFileName(managedResource.filename),
754 managedResource.isPublic?
755 ResourceAttributes.Public:
756 ResourceAttributes.Private);
757 }else{
758 try{
759 using (ResourceReader reader = new ResourceReader(managedResource.filename))
761 IResourceWriter writer = this.CompilerGlobals.module.DefineResource(managedResource.name,
762 managedResource.filename,
763 managedResource.isPublic?
764 ResourceAttributes.Public:
765 ResourceAttributes.Private);
766 foreach (DictionaryEntry resource in reader)
767 writer.AddResource((string)resource.Key, resource.Value);
769 }catch(System.ArgumentException){
770 JScriptException se = new JScriptException(JSError.InvalidResource);
771 se.value = managedResource.filename;
772 this.OnCompilerError(se);
773 this.isEngineCompiled = false;
774 return false;
780 if (this.isEngineCompiled)
781 this.EmitReferences();
783 // Save things out to a local PE file when doSaveAfterCompile is set; this is set when an
784 // output name is given (allows JSC to avoid IVsaEngine.SaveCompiledState). The proper
785 // values for VSA are doSaveAfterCompile == false and genStartupClass == true. We allow
786 // genStartupClass to be false for scenarios like JSTest and the Debugger
787 if (this.isEngineCompiled){
788 if (this.doSaveAfterCompile){
789 if (this.PEFileKind != PEFileKinds.Dll)
790 this.CreateMain();
791 // After executing this code path, it is an error to call SaveCompiledState (until the engine is recompiled)
792 try{
793 compilerGlobals.assemblyBuilder.Save(Path.GetFileName(this.PEFileName),
794 this.PEKindFlags, this.PEMachineArchitecture);
795 }catch(Exception e){
796 throw new VsaException(VsaError.SaveCompiledStateFailed, e.Message, e);
797 }catch{
798 throw new VsaException(VsaError.SaveCompiledStateFailed);
800 }else if (this.genStartupClass){
801 // this is generated for VSA hosting
802 this.CreateStartupClass();
805 return this.isEngineCompiled;
808 internal CultureInfo ErrorCultureInfo{
809 get{
810 if (this.errorCultureInfo == null || this.errorCultureInfo.LCID != this.errorLocale)
811 this.errorCultureInfo = new CultureInfo(this.errorLocale);
812 return this.errorCultureInfo;
816 private string GenerateRandomPEFileName(){
817 if (this.randomNumberGenerator == null)
818 this.randomNumberGenerator = new RNGCryptoServiceProvider();
819 // Generate random bytes
820 byte[] data = new byte[6];
821 this.randomNumberGenerator.GetBytes(data);
822 // Turn them into a string containing only characters valid in file names
823 string randomString = System.Convert.ToBase64String(data);
824 randomString = randomString.Replace('/', '-');
825 randomString = randomString.Replace('+', '_');
826 // Use the first random filename as the engine's temp directory name
827 if (this.tempDirectory == null)
828 this.tempDirectory = System.IO.Path.GetTempPath() + randomString;
829 string filename = randomString + (this.PEFileKind == PEFileKinds.Dll? ".dll": ".exe");
830 return this.tempDirectory + Path.DirectorySeparatorChar + filename;
833 /////////////////////////////////////////////////////////////////////////////
835 // Security Issue
837 /////////////////////////////////////////////////////////////////////////////
839 // [EricLi] 10 November 2001
841 // Right now the VsaEngine class requires full trust to use as
842 // an engine that runs code or generates assemblies.
844 // Preventing untrusted callers from actually compiling and
845 // running code is clearly undesirable -- we want partially-
846 // trusted host scenarios to work. For this release however
847 // there are too many poorly-understood issues involving
848 // controling the evidence property.
850 /////////////////////////////////////////////////////////////////////////////
852 [PermissionSet(SecurityAction.Demand, Name="FullTrust")]
853 public Assembly GetAssembly(){
854 this.TryObtainLock();
855 try{
856 if (null != this.PEFileName)
857 return Assembly.LoadFrom(this.PEFileName);
858 else
859 return compilerGlobals.assemblyBuilder;
860 }finally{
861 this.ReleaseLock();
865 internal ClassScope GetClass(String className){
866 if (this.packages != null)
867 for (int i = 0, n = this.packages.Count; i < n; i++){
868 PackageScope pscope = (PackageScope)this.packages[i];
869 Object pval = pscope.GetMemberValue(className, 1);
870 if (!(pval is Microsoft.JScript.Missing)){
871 ClassScope csc = (ClassScope)pval;
872 return csc;
875 return null;
878 [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
879 public IVsaItem GetItem(String itemName){
880 return this.vsaItems[itemName];
883 [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
884 public IVsaItem GetItemAtIndex(int index){
885 return this.vsaItems[index];
888 [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
889 public int GetItemCount(){
890 return this.vsaItems.Count;
893 public IVsaScriptScope GetGlobalScope(){
894 if (null == this.globalScope){
895 this.globalScope = new VsaScriptScope(this, "Global", null);
896 GlobalScope scope = (GlobalScope)this.globalScope.GetObject();
897 scope.globalObject = this.Globals.globalObject;
898 scope.fast = this.doFast;
899 scope.isKnownAtCompileTime = this.doFast;
901 return this.globalScope;
904 // Called by the debugger to get hold of the global scope from within a class method
905 public GlobalScope GetMainScope(){
906 ScriptObject o = ScriptObjectStackTop();
907 while (o != null && !(o is GlobalScope))
908 o = o.GetParent();
909 return (GlobalScope)o;
912 public Module GetModule(){
913 if (null != this.PEFileName){
914 Assembly a = GetAssembly();
915 Module[] modules = a.GetModules();
916 return modules[0];
917 }else
918 return this.CompilerGlobals.module;
921 public ArrayConstructor GetOriginalArrayConstructor(){
922 return this.Globals.globalObject.originalArray;
925 public ObjectConstructor GetOriginalObjectConstructor(){
926 return this.Globals.globalObject.originalObject;
929 public RegExpConstructor GetOriginalRegExpConstructor(){
930 return this.Globals.globalObject.originalRegExp;
933 protected override Object GetCustomOption(String name){
934 if (String.Compare(name, "CLSCompliant", StringComparison.OrdinalIgnoreCase) == 0)
935 return this.isCLSCompliant;
936 else if (String.Compare(name, "fast", StringComparison.OrdinalIgnoreCase) == 0)
937 return this.doFast;
938 else if (String.Compare(name, "output", StringComparison.OrdinalIgnoreCase) == 0)
939 return this.PEFileName;
940 else if (String.Compare(name, "PEFileKind", StringComparison.OrdinalIgnoreCase) == 0)
941 return this.PEFileKind;
942 else if (String.Compare(name, "PortableExecutableKind", StringComparison.OrdinalIgnoreCase) == 0)
943 return this.PEKindFlags;
944 else if (String.Compare(name, "ImageFileMachine", StringComparison.OrdinalIgnoreCase) == 0)
945 return this.PEMachineArchitecture;
946 else if (String.Compare(name, "ReferenceLoaderAPI", StringComparison.OrdinalIgnoreCase) == 0) {
947 switch (this.ReferenceLoaderAPI) {
948 case LoaderAPI.LoadFrom: return "LoadFrom";
949 case LoaderAPI.LoadFile: return "LoadFile";
950 case LoaderAPI.ReflectionOnlyLoadFrom: return "ReflectionOnlyLoadFrom";
951 default: throw new VsaException(VsaError.OptionNotSupported);
954 else if (String.Compare(name, "print", StringComparison.OrdinalIgnoreCase) == 0)
955 return this.doPrint;
956 else if (String.Compare(name, "UseContextRelativeStatics", StringComparison.OrdinalIgnoreCase) == 0)
957 return this.doCRS;
958 // the next two are needed because of the ICompiler interface. They should not fail even though they may not do anything
959 else if (String.Compare(name, "optimize", StringComparison.OrdinalIgnoreCase) == 0)
960 return null;
961 else if (String.Compare(name, "define", StringComparison.OrdinalIgnoreCase) == 0)
962 return null;
963 else if (String.Compare(name, "defines", StringComparison.OrdinalIgnoreCase) == 0)
964 return this.Defines;
965 else if (String.Compare(name, "ee", StringComparison.OrdinalIgnoreCase) == 0)
966 return VsaEngine.executeForJSEE;
967 else if (String.Compare(name, "version", StringComparison.OrdinalIgnoreCase) == 0)
968 return this.versionInfo;
969 else if (String.Compare(name, "VersionSafe", StringComparison.OrdinalIgnoreCase) == 0)
970 return this.versionSafe;
971 else if (String.Compare(name, "warnaserror", StringComparison.OrdinalIgnoreCase) == 0)
972 return this.doWarnAsError;
973 else if (String.Compare(name, "WarningLevel", StringComparison.OrdinalIgnoreCase) == 0)
974 return this.nWarningLevel;
975 else if (String.Compare(name, "managedResources", StringComparison.OrdinalIgnoreCase) == 0)
976 return this.managedResources;
977 else if (String.Compare(name, "alwaysGenerateIL", StringComparison.OrdinalIgnoreCase) == 0)
978 return this.alwaysGenerateIL;
979 else if (String.Compare(name, "DebugDirectory", StringComparison.OrdinalIgnoreCase) == 0)
980 return this.debugDirectory;
981 else if (String.Compare(name, "AutoRef", StringComparison.OrdinalIgnoreCase) == 0)
982 return this.autoRef;
983 else
984 throw new VsaException(VsaError.OptionNotSupported);
987 internal int GetStaticCodeBlockCount(){
988 return ((VsaItems)this.vsaItems).staticCodeBlockCount;
991 internal Type GetType(String typeName){
992 if (this.cachedTypeLookups == null)
993 this.cachedTypeLookups = new SimpleHashtable(1000);
994 object cacheResult = this.cachedTypeLookups[typeName];
995 if (cacheResult == null){
996 // proceed with lookup
997 for (int i = 0, n = this.Scopes.Count; i < n; i++){
998 GlobalScope scope = (GlobalScope)this.scopes[i];
999 Type result = Globals.TypeRefs.ToReferenceContext(scope.GetType()).Assembly.GetType(typeName, false);
1000 if (result != null){
1001 this.cachedTypeLookups[typeName] = result;
1002 return result;
1006 if (this.runtimeAssembly != null) {
1007 this.AddReferences();
1008 this.runtimeAssembly = null;
1011 for (int i = 0, n = this.vsaItems.Count; i < n; i++){
1012 object item = this.vsaItems[i];
1013 if (item is VsaReference){
1014 Type result = ((VsaReference)item).GetType(typeName);
1015 if (result != null){
1016 this.cachedTypeLookups[typeName] = result;
1017 return result;
1021 if (this.implicitAssemblies == null){
1022 this.cachedTypeLookups[typeName] = false;
1023 return null;
1025 for (int i = 0, n = this.implicitAssemblies.Count; i < n; i++){
1026 Assembly assembly = (Assembly)this.implicitAssemblies[i];
1027 Type result = assembly.GetType(typeName, false);
1028 if (result != null){
1029 if (!result.IsPublic || CustomAttribute.IsDefined(result, typeof(System.Runtime.CompilerServices.RequiredAttributeAttribute), true))
1030 result = null; //Suppress the type if it is not public or if it is a funky C++ type.
1031 else{
1032 this.cachedTypeLookups[typeName] = result;
1033 return result;
1038 this.cachedTypeLookups[typeName] = false;
1039 return null;
1041 return (cacheResult as Type);
1044 internal Globals Globals{
1045 get{
1046 if (this.globals == null)
1047 this.globals = new Globals(this.doFast, this);
1048 return this.globals;
1052 internal bool HasErrors{
1053 get{
1054 return this.numberOfErrors != 0;
1058 // GetScannerInstance is used by IsValidNamespaceName and IsValidIdentifier to validate names.
1059 // We return an instance of the scanner only if there is no whitespace in the name text, since
1060 // we do not want to allow, say, "not. valid" to be a valid namespace name even though that
1061 // would produce a valid sequence of tokens.
1062 private JSScanner GetScannerInstance(string name){
1063 // make sure there's no whitespace in the name (values copied from documentation on String.Trim())
1064 char[] anyWhiteSpace = {
1065 (char)0x0009, (char)0x000A, (char)0x000B, (char)0x000C, (char)0x000D, (char)0x0020, (char)0x00A0,
1066 (char)0x2000, (char)0x2001, (char)0x2002, (char)0x2003, (char)0x2004, (char)0x2005, (char)0x2006,
1067 (char)0x2007, (char)0x2008, (char)0x2009, (char)0x200A, (char)0x200B, (char)0x3000, (char)0xFEFF
1069 if (name == null || name.IndexOfAny(anyWhiteSpace) > -1)
1070 return null;
1071 // Create a code item whose source is the given text
1072 VsaItem item = new VsaStaticCode(this, "itemName", VsaItemFlag.None);
1073 Context context = new Context(new DocumentContext(item), name);
1074 context.errorReported = -1;
1075 JSScanner scanner = new JSScanner(); //Use this constructor to avoid allocating a Globals instance
1076 scanner.SetSource(context);
1077 return scanner;
1080 // Use this method to initialize the engine for non-VSA use. This includes JSC, JSTest, and the JSEE.
1081 [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
1082 public void InitVsaEngine(string rootMoniker, IVsaSite site){
1083 this.genStartupClass = false;
1084 this.engineMoniker = rootMoniker;
1085 this.engineSite = site;
1086 this.isEngineInitialized = true;
1087 this.rootNamespace = "JScript.DefaultNamespace";
1088 this.isEngineDirty = true;
1089 this.isEngineCompiled = false;
1092 [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
1093 public void Interrupt(){
1094 if (this.runningThread != null){
1095 this.runningThread.Abort();
1096 this.runningThread = null;
1100 protected override bool IsValidNamespaceName(string name){
1101 JSScanner scanner = this.GetScannerInstance(name);
1102 if (scanner == null)
1103 return false;
1104 while(true){
1105 if (scanner.PeekToken() != JSToken.Identifier)
1106 return false;
1107 scanner.GetNextToken();
1108 if (scanner.PeekToken() == JSToken.EndOfFile)
1109 break;
1110 if (scanner.PeekToken() != JSToken.AccessField)
1111 return false;
1112 scanner.GetNextToken();
1114 return true;
1117 [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
1118 public override bool IsValidIdentifier(string ident){
1119 JSScanner scanner = this.GetScannerInstance(ident);
1120 if (scanner == null)
1121 return false;
1122 if (scanner.PeekToken() != JSToken.Identifier)
1123 return false;
1124 scanner.GetNextToken();
1125 if (scanner.PeekToken() != JSToken.EndOfFile)
1126 return false;
1127 return true;
1130 public LenientGlobalObject LenientGlobalObject{
1131 get{
1132 return (LenientGlobalObject)this.Globals.globalObject;
1136 protected override Assembly LoadCompiledState(){
1137 Debug.Assert(this.haveCompiledState);
1138 byte[] pe;
1139 byte[] pdb;
1140 if (!this.genDebugInfo) {
1141 System.Security.Policy.Evidence compilationEvidence = this.CompilerGlobals.compilationEvidence;
1142 System.Security.Policy.Evidence executionEvidence = this.executionEvidence;
1143 if (compilationEvidence == null && executionEvidence == null ||
1144 compilationEvidence != null && compilationEvidence.Equals(executionEvidence))
1145 return this.compilerGlobals.assemblyBuilder;
1147 // we need to save/reload to properly associate debug symbols with the assembly
1148 this.DoSaveCompiledState(out pe, out pdb);
1149 return Assembly.Load(pe, pdb, this.executionEvidence);
1152 protected override void DoLoadSourceState(IVsaPersistSite site){
1153 // DoSaveSourceState puts everything in the project item (use null for the name)
1154 // We assume the site is valid and contains a valid project file so any errors are
1155 // wrapped in a VsaException and thrown
1156 string projectElement = site.LoadElement(null);
1157 try{
1158 XmlDocument project = new XmlDocument();
1159 project.LoadXml(projectElement);
1160 XmlElement root = project.DocumentElement;
1162 // verify that we support this version of the project file
1163 if (this.LoadProjectVersion(root) == CurrentProjectVersion){
1164 this.LoadVsaEngineState(root);
1165 this.isEngineDirty = false;
1167 }catch(Exception e){
1168 throw new VsaException(VsaError.UnknownError, e.ToString(), e);
1169 }catch{
1170 throw new VsaException(VsaError.UnknownError);
1174 private Version LoadProjectVersion(XmlElement root){
1175 return new Version(root["ProjectVersion"].GetAttribute("Version"));
1178 private void LoadVsaEngineState(XmlElement parent){
1179 XmlElement engine = parent["VsaEngine"];
1180 this.applicationPath = engine.GetAttribute("ApplicationBase");
1181 this.genDebugInfo = Boolean.Parse(engine.GetAttribute("GenerateDebugInfo"));
1182 this.scriptLanguage = engine.GetAttribute("Language");
1183 this.LCID = Int32.Parse(engine.GetAttribute("LCID"), CultureInfo.InvariantCulture);
1184 this.Name = engine.GetAttribute("Name");
1185 this.rootNamespace = engine.GetAttribute("RootNamespace");
1186 this.assemblyVersion = engine.GetAttribute("Version");
1187 this.LoadCustomOptions(engine);
1188 this.LoadVsaItems(engine);
1191 private void LoadCustomOptions(XmlElement parent){
1192 XmlElement options = parent["Options"];
1193 Debug.Assert(String.Compare(options.Name, "Options", StringComparison.OrdinalIgnoreCase) == 0);
1194 this.doFast = Boolean.Parse(options.GetAttribute("fast"));
1195 this.doPrint = Boolean.Parse(options.GetAttribute("print"));
1196 this.doCRS = Boolean.Parse(options.GetAttribute("UseContextRelativeStatics"));
1197 this.versionSafe = Boolean.Parse(options.GetAttribute("VersionSafe"));
1198 this.libpath = options.GetAttribute("libpath");
1199 this.doWarnAsError = Boolean.Parse(options.GetAttribute("warnaserror"));
1200 this.nWarningLevel = Int32.Parse(options.GetAttribute("WarningLevel"), CultureInfo.InvariantCulture);
1201 this.LoadUserDefines(options);
1202 this.LoadManagedResources(options);
1205 private void LoadUserDefines(XmlElement parent){
1206 XmlElement userDefines = parent["Defines"];
1207 XmlNodeList defines = userDefines.ChildNodes;
1208 foreach (XmlElement definition in defines)
1209 this.Defines[definition.Name] = definition.GetAttribute("Value");
1212 private void LoadManagedResources(XmlElement parent){
1213 XmlElement resources = parent["ManagedResources"];
1214 XmlNodeList managedResources = resources.ChildNodes;
1215 if (managedResources.Count > 0){
1216 this.managedResources = new ArrayList(managedResources.Count);
1217 foreach (XmlElement resource in managedResources){
1218 string name = resource.GetAttribute("Name");
1219 string filename = resource.GetAttribute("FileName");
1220 bool isPublic = Boolean.Parse(resource.GetAttribute("Public"));
1221 bool isLinked = Boolean.Parse(resource.GetAttribute("Linked"));
1222 ((ArrayList)this.managedResources).Add(new ResInfo(filename, name, isPublic, isLinked));
1227 private void LoadVsaItems(XmlElement parent){
1228 XmlNodeList vsaItems = parent["VsaItems"].ChildNodes;
1229 string itemType;
1230 IVsaItem item;
1231 string reference = VsaItemType.Reference.ToString();
1232 string appGlobal = VsaItemType.AppGlobal.ToString();
1233 string code = VsaItemType.Code.ToString();
1234 foreach (XmlElement vsaItem in vsaItems){
1235 string name = vsaItem.GetAttribute("Name");
1236 itemType = vsaItem.GetAttribute("ItemType");
1237 if (String.Compare(itemType, reference, StringComparison.OrdinalIgnoreCase) == 0){
1238 item = this.vsaItems.CreateItem(name, VsaItemType.Reference, VsaItemFlag.None);
1239 ((IVsaReferenceItem)item).AssemblyName = vsaItem.GetAttribute("AssemblyName");
1240 }else if (String.Compare(itemType, appGlobal, StringComparison.OrdinalIgnoreCase) == 0){
1241 item = this.vsaItems.CreateItem(name, VsaItemType.AppGlobal, VsaItemFlag.None);
1242 ((IVsaGlobalItem)item).ExposeMembers = Boolean.Parse(vsaItem.GetAttribute("ExposeMembers"));
1243 ((IVsaGlobalItem)item).TypeString = vsaItem.GetAttribute("TypeString");
1244 }else if (String.Compare(itemType, code, StringComparison.OrdinalIgnoreCase) == 0){
1245 item = this.vsaItems.CreateItem(name, VsaItemType.Code, VsaItemFlag.None);
1246 XmlCDataSection sourceText = (XmlCDataSection)vsaItem.FirstChild;
1247 string unescapedText = sourceText.Value.Replace(" >", ">");
1248 ((IVsaCodeItem)item).SourceText = unescapedText;
1249 }else
1250 throw new VsaException(VsaError.LoadElementFailed);
1251 XmlNodeList vsaItemOptions = vsaItem["Options"].ChildNodes;
1252 foreach (XmlElement option in vsaItemOptions){
1253 item.SetOption(option.Name, option.GetAttribute("Value"));
1255 ((VsaItem)item).IsDirty = false;
1259 internal bool OnCompilerError(JScriptException se){
1260 if (se.Severity == 0 || (this.doWarnAsError && se.Severity <= this.nWarningLevel))
1261 this.numberOfErrors++;
1262 bool canRecover = this.engineSite.OnCompilerError(se); //true means carry on with compilation.
1263 if (!canRecover)
1264 this.isEngineCompiled = false;
1265 return canRecover;
1268 public ScriptObject PopScriptObject(){
1269 return (ScriptObject)this.Globals.ScopeStack.Pop();
1272 public void PushScriptObject(ScriptObject obj){
1273 this.Globals.ScopeStack.Push(obj);
1276 [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
1277 public void RegisterEventSource(String name){
1280 [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
1281 public override void Reset(){
1282 if (this.genStartupClass)
1283 base.Reset();
1284 else
1285 this.ResetCompiledState();
1288 protected override void ResetCompiledState(){
1289 if (this.globalScope != null){
1290 this.globalScope.Reset();
1291 this.globalScope = null;
1293 this.classCounter = 0;
1294 this.haveCompiledState = false;
1295 this.failedCompilation = true;
1296 this.compiledRootNamespace = null;
1297 this.startupClass = null;
1298 this.compilerGlobals = null;
1299 this.globals = null;
1300 foreach (Object item in this.vsaItems)
1301 ((VsaItem)item).Reset();
1302 this.implicitAssemblies = null;
1303 this.implicitAssemblyCache = null;
1304 this.cachedTypeLookups = null;
1305 this.isEngineCompiled = false;
1306 this.isEngineRunning = false;
1307 this.isCompilerSet = false;
1308 this.packages = null;
1309 if (!this.doSaveAfterCompile)
1310 this.PEFileName = null;
1311 this.rawPE = null;
1312 this.rawPDB = null;
1315 // the debugger restart the engine to run different expression evaluation
1316 [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
1317 public void Restart(){
1318 this.TryObtainLock();
1319 try{
1320 ((VsaItems)this.vsaItems).Close();
1321 if (null != this.globalScope)
1322 this.globalScope.Close();
1323 this.globalScope = null;
1324 this.vsaItems = new VsaItems(this);
1325 this.isEngineRunning = false;
1326 this.isEngineCompiled = false;
1327 this.isCompilerSet = false;
1328 this.isClosed = false;
1329 this.runningThread = null;
1330 this.globals = null;
1331 }finally{
1332 this.ReleaseLock();
1336 [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
1337 public void RunEmpty(){
1338 this.TryObtainLock();
1339 try{
1340 Preconditions(Pre.EngineNotClosed | Pre.RootMonikerSet | Pre.SiteSet);
1341 this.isEngineRunning = true;
1342 // save the current thread so it can be interrupted
1343 this.runningThread = Thread.CurrentThread;
1344 if (null != this.globalScope)
1345 this.globalScope.Run();
1346 foreach (Object item in this.vsaItems)
1347 ((VsaItem)item).Run();
1348 }finally{
1349 this.runningThread = null;
1350 this.ReleaseLock();
1354 [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
1355 public void Run(AppDomain domain){
1356 // managed engines are not supporting Run in user-provided AppDomains
1357 throw new System.NotImplementedException();
1360 protected override void DoSaveCompiledState(out byte[] pe, out byte[] pdb){
1361 pe = null;
1362 pdb = null;
1363 if (this.rawPE == null){
1364 try{
1365 // Save things out to a local PE file, then read back into memory
1366 // PEFileName was set in the Compile method and we must have compiled in order to be calling this
1367 if (!Directory.Exists(this.tempDirectory))
1368 Directory.CreateDirectory(this.tempDirectory);
1369 this.compilerGlobals.assemblyBuilder.Save(Path.GetFileName(this.PEFileName),
1370 this.PEKindFlags, this.PEMachineArchitecture);
1371 string tempPDBName = Path.ChangeExtension(this.PEFileName, ".ildb");
1372 try{
1373 FileStream stream = new FileStream(this.PEFileName, FileMode.Open, FileAccess.Read, FileShare.Read);
1374 try{
1375 this.rawPE = new byte[(int)stream.Length];
1376 stream.Read(this.rawPE, 0, this.rawPE.Length);
1377 }finally{
1378 stream.Close();
1380 // genDebugInfo could have been changed since we compiled, so check to make sure the symbols are there
1381 if (File.Exists(tempPDBName)){
1382 stream = new FileStream(tempPDBName, FileMode.Open, FileAccess.Read, FileShare.Read);
1383 try{
1384 this.rawPDB = new byte[(int)stream.Length];
1385 stream.Read(this.rawPDB, 0, this.rawPDB.Length);
1386 }finally{
1387 stream.Close();
1390 }finally{
1391 File.Delete(this.PEFileName);
1392 if (File.Exists(tempPDBName))
1393 File.Delete(tempPDBName);
1395 }catch(Exception e){
1396 throw new VsaException(VsaError.SaveCompiledStateFailed, e.ToString(), e);
1397 }catch{
1398 throw new VsaException(VsaError.SaveCompiledStateFailed);
1401 pe = this.rawPE;
1402 pdb = this.rawPDB;
1405 protected override void DoSaveSourceState(IVsaPersistSite site){
1406 XmlDocument project = new XmlDocument();
1407 project.LoadXml("<project></project>");
1408 XmlElement root = project.DocumentElement;
1409 this.SaveProjectVersion(project, root);
1410 this.SaveVsaEngineState(project, root);
1411 site.SaveElement(null, project.OuterXml);
1412 this.SaveSourceForDebugging();
1413 this.isEngineDirty = false;
1416 private void SaveSourceForDebugging(){
1417 if (!this.GenerateDebugInfo || this.debugDirectory == null || !this.isEngineDirty)
1418 return;
1419 foreach (VsaItem item in this.vsaItems){
1420 if (item is VsaStaticCode){
1421 string fileName = this.debugDirectory + item.Name + ".js";
1422 try{
1423 using (FileStream file = new FileStream(fileName, FileMode.Create, FileAccess.Write)) {
1424 using (StreamWriter sw = new StreamWriter(file))
1425 sw.Write(((VsaStaticCode)item).SourceText);
1426 item.SetOption("codebase", fileName);
1428 }catch{
1429 // swallow any file creation exceptions
1435 private void SaveProjectVersion(XmlDocument project, XmlElement root){
1436 XmlElement version = project.CreateElement("ProjectVersion");
1437 this.CreateAttribute(project, version, "Version", CurrentProjectVersion.ToString());
1438 root.AppendChild(version);
1441 private void SaveVsaEngineState(XmlDocument project, XmlElement parent){
1442 XmlElement engine = project.CreateElement("VsaEngine");
1443 // add IVsaEngine properties as attributes
1444 this.CreateAttribute(project, engine, "ApplicationBase", this.applicationPath);
1445 this.CreateAttribute(project, engine, "GenerateDebugInfo", this.genDebugInfo.ToString());
1446 this.CreateAttribute(project, engine, "Language", this.scriptLanguage);
1447 this.CreateAttribute(project, engine, "LCID", this.errorLocale.ToString(CultureInfo.InvariantCulture));
1448 this.CreateAttribute(project, engine, "Name", this.engineName);
1449 this.CreateAttribute(project, engine, "RootNamespace", this.rootNamespace);
1450 this.CreateAttribute(project, engine, "Version", this.assemblyVersion);
1451 this.SaveCustomOptions(project, engine);
1452 this.SaveVsaItems(project, engine);
1453 parent.AppendChild(engine);
1456 private void SaveCustomOptions(XmlDocument project, XmlElement parent){
1457 XmlElement options = project.CreateElement("Options");
1458 this.CreateAttribute(project, options, "fast", this.doFast.ToString());
1459 this.CreateAttribute(project, options, "print", this.doPrint.ToString());
1460 this.CreateAttribute(project, options, "UseContextRelativeStatics", this.doCRS.ToString());
1461 this.CreateAttribute(project, options, "VersionSafe", this.versionSafe.ToString());
1462 this.CreateAttribute(project, options, "libpath", this.libpath);
1463 this.CreateAttribute(project, options, "warnaserror", this.doWarnAsError.ToString());
1464 this.CreateAttribute(project, options, "WarningLevel", this.nWarningLevel.ToString(CultureInfo.InvariantCulture));
1465 this.SaveUserDefines(project, options);
1466 this.SaveManagedResources(project, options);
1467 parent.AppendChild(options);
1470 private void SaveUserDefines(XmlDocument project, XmlElement parent){
1471 XmlElement userDefines = project.CreateElement("Defines");
1472 if (this.Defines != null){
1473 foreach (string key in this.Defines.Keys){
1474 this.AddChildAndValue(project, userDefines, key, (string)this.Defines[key]);
1477 parent.AppendChild(userDefines);
1480 private void SaveManagedResources(XmlDocument project, XmlElement parent){
1481 // Save managed resources
1482 XmlElement managedResources = project.CreateElement("ManagedResources");
1483 if (this.managedResources != null){
1484 foreach (ResInfo resinfo in this.managedResources){
1485 XmlElement resource = project.CreateElement(resinfo.name);
1486 this.CreateAttribute(project, resource, "File", resinfo.filename);
1487 this.CreateAttribute(project, resource, "Public", resinfo.isPublic.ToString());
1488 this.CreateAttribute(project, resource, "Linked", resinfo.isLinked.ToString());
1489 managedResources.AppendChild(resource);
1492 parent.AppendChild(managedResources);
1495 private void SaveVsaItems(XmlDocument project, XmlElement parent){
1496 XmlElement vsaItems = project.CreateElement("VsaItems");
1497 foreach (IVsaItem item in this.vsaItems){
1498 XmlElement vsaItem = project.CreateElement("IVsaItem");
1499 this.CreateAttribute(project, vsaItem, "Name", item.Name);
1500 this.CreateAttribute(project, vsaItem, "ItemType", item.ItemType.ToString(CultureInfo.InvariantCulture));
1501 XmlElement vsaItemOptions = project.CreateElement("Options");
1502 if (item is VsaHostObject){
1503 // VsaItemType.AppGlobal
1504 this.CreateAttribute(project, vsaItem, "TypeString", ((VsaHostObject)item).TypeString);
1505 this.CreateAttribute(project, vsaItem, "ExposeMembers", ((VsaHostObject)item).ExposeMembers.ToString(CultureInfo.InvariantCulture));
1506 }else if (item is VsaReference){
1507 // VsaItemType.Reference
1508 CreateAttribute(project, vsaItem, "AssemblyName", ((VsaReference)item).AssemblyName);
1509 }else if (item is VsaStaticCode){
1510 // VsaItemType.Code
1511 string escapedText = ((VsaStaticCode)item).SourceText.Replace(">", " >");
1512 XmlCDataSection source = project.CreateCDataSection(escapedText);
1513 vsaItem.AppendChild(source);
1514 string codebase = (string)item.GetOption("codebase");
1515 if (codebase != null)
1516 this.AddChildAndValue(project, vsaItemOptions, "codebase", codebase);
1517 }else
1518 throw new VsaException(VsaError.SaveElementFailed);
1519 ((VsaItem)item).IsDirty = false;
1520 vsaItem.AppendChild(vsaItemOptions);
1521 vsaItems.AppendChild(vsaItem);
1523 parent.AppendChild(vsaItems);
1526 internal ArrayList Scopes{
1527 get{
1528 if (this.scopes == null)
1529 this.scopes = new ArrayList(8);
1530 return this.scopes;
1534 public ScriptObject ScriptObjectStackTop(){
1535 return (ScriptObject)this.Globals.ScopeStack.Peek();
1538 internal void SetEnclosingContext(ScriptObject ob){
1539 ScriptObject s = this.Globals.ScopeStack.Peek();
1540 while (s.GetParent() != null)
1541 s = s.GetParent();
1542 s.SetParent(ob);
1545 public void SetOutputStream(IMessageReceiver output){
1546 COMCharStream stream = new COMCharStream(output);
1547 System.IO.StreamWriter writer = new System.IO.StreamWriter(stream, Encoding.Default);
1548 writer.AutoFlush = true;
1549 ScriptStream.Out = writer;
1550 ScriptStream.Error = writer;
1553 protected override void SetCustomOption(String name, Object value){
1554 try{
1555 if (String.Compare(name, "CLSCompliant", StringComparison.OrdinalIgnoreCase) == 0)
1556 this.isCLSCompliant = (bool)value;
1557 else if (String.Compare(name, "fast", StringComparison.OrdinalIgnoreCase) == 0)
1558 this.doFast = (bool)value;
1559 else if (String.Compare(name, "output", StringComparison.OrdinalIgnoreCase) == 0){
1560 if (value is String){
1561 this.PEFileName = (String)value;
1562 this.doSaveAfterCompile = true;
1564 }else if (String.Compare(name, "PEFileKind", StringComparison.OrdinalIgnoreCase) == 0)
1565 this.PEFileKind = (PEFileKinds)value;
1566 else if (String.Compare(name, "PortableExecutableKind", StringComparison.OrdinalIgnoreCase) == 0)
1567 this.PEKindFlags = (PortableExecutableKinds)value;
1568 else if (String.Compare(name, "ImageFileMachine", StringComparison.OrdinalIgnoreCase) == 0)
1569 this.PEMachineArchitecture = (ImageFileMachine)value;
1570 else if (String.Compare(name, "ReferenceLoaderAPI", StringComparison.OrdinalIgnoreCase) == 0) {
1571 String loaderAPI = (string)value;
1572 if (String.Compare(loaderAPI, "LoadFrom", StringComparison.OrdinalIgnoreCase) == 0)
1573 this.ReferenceLoaderAPI = LoaderAPI.LoadFrom;
1574 else if (String.Compare(loaderAPI, "LoadFile", StringComparison.OrdinalIgnoreCase) == 0)
1575 this.ReferenceLoaderAPI = LoaderAPI.LoadFile;
1576 else if (String.Compare(loaderAPI, "ReflectionOnlyLoadFrom", StringComparison.OrdinalIgnoreCase) == 0)
1577 this.ReferenceLoaderAPI = LoaderAPI.ReflectionOnlyLoadFrom;
1578 else
1579 throw new VsaException(VsaError.OptionInvalid);
1581 else if (String.Compare(name, "print", StringComparison.OrdinalIgnoreCase) == 0)
1582 this.doPrint = (bool)value;
1583 else if (String.Compare(name, "UseContextRelativeStatics", StringComparison.OrdinalIgnoreCase) == 0)
1584 this.doCRS = (bool)value;
1585 // the next two are needed because of the ICompiler interface. They should not fail even though they may not do anything
1586 else if (String.Compare(name, "optimize", StringComparison.OrdinalIgnoreCase) == 0)
1587 return;
1588 else if (String.Compare(name, "define", StringComparison.OrdinalIgnoreCase) == 0)
1589 return;
1590 else if (String.Compare(name, "defines", StringComparison.OrdinalIgnoreCase) == 0)
1591 this.Defines = (Hashtable)value;
1592 else if (String.Compare(name, "ee", StringComparison.OrdinalIgnoreCase) == 0)
1593 VsaEngine.executeForJSEE = (Boolean)value;
1594 else if (String.Compare(name, "version", StringComparison.OrdinalIgnoreCase) == 0)
1595 this.versionInfo = (Version)value;
1596 else if (String.Compare(name, "VersionSafe", StringComparison.OrdinalIgnoreCase) == 0)
1597 this.versionSafe = (Boolean)value;
1598 else if (String.Compare(name, "libpath", StringComparison.OrdinalIgnoreCase) == 0)
1599 this.libpath = (String)value;
1600 else if (String.Compare(name, "warnaserror", StringComparison.OrdinalIgnoreCase) == 0)
1601 this.doWarnAsError = (bool)value;
1602 else if (String.Compare(name, "WarningLevel", StringComparison.OrdinalIgnoreCase) == 0)
1603 this.nWarningLevel = (int)value;
1604 else if (String.Compare(name, "managedResources", StringComparison.OrdinalIgnoreCase) == 0)
1605 this.managedResources = (ICollection)value;
1606 else if (String.Compare(name, "alwaysGenerateIL", StringComparison.OrdinalIgnoreCase) == 0)
1607 this.alwaysGenerateIL = (bool)value;
1608 else if (String.Compare(name, "DebugDirectory", StringComparison.OrdinalIgnoreCase) == 0){
1609 // use null to turn off SaveSourceState source generation
1610 if (value == null){
1611 this.debugDirectory = null;
1612 return;
1614 string dir = value as string;
1615 if (dir == null)
1616 throw new VsaException(VsaError.OptionInvalid);
1617 try{
1618 dir = Path.GetFullPath(dir + Path.DirectorySeparatorChar);
1619 if (!Directory.Exists(dir))
1620 Directory.CreateDirectory(dir);
1621 }catch(Exception e){
1622 // we couldn't create the specified directory
1623 throw new VsaException(VsaError.OptionInvalid, "", e);
1624 }catch{
1625 // we couldn't create the specified directory
1626 throw new VsaException(VsaError.OptionInvalid);
1628 this.debugDirectory = dir;
1629 }else if (String.Compare(name, "AutoRef", StringComparison.OrdinalIgnoreCase) == 0)
1630 this.autoRef = (bool)value;
1631 else
1632 throw new VsaException(VsaError.OptionNotSupported);
1633 }catch(VsaException){
1634 throw;
1635 }catch{
1636 throw new VsaException(VsaError.OptionInvalid);
1640 internal void SetUpCompilerEnvironment(){
1641 if (!this.isCompilerSet){
1642 Microsoft.JScript.Globals.TypeRefs = this.TypeRefs;
1643 this.globals = this.Globals;
1644 this.isCompilerSet = true;
1648 internal void TryToAddImplicitAssemblyReference(String name){
1649 if (!this.autoRef) return;
1651 String key;
1652 SimpleHashtable implictAssemblyCache = this.implicitAssemblyCache;
1653 if (implicitAssemblyCache == null) {
1654 //Populate cache with things that should not be autoref'd. Canonical form is lower case without extension.
1655 implicitAssemblyCache = new SimpleHashtable(50);
1657 //PEFileName always includes an extension and is never NULL.
1658 implicitAssemblyCache[Path.GetFileNameWithoutExtension(this.PEFileName).ToLowerInvariant()] = true;
1660 foreach (Object item in this.vsaItems){
1661 VsaReference assemblyReference = item as VsaReference;
1662 if (assemblyReference == null || assemblyReference.AssemblyName == null) continue;
1663 key = Path.GetFileName(assemblyReference.AssemblyName).ToLowerInvariant();
1664 if (key.EndsWith(".dll", StringComparison.Ordinal))
1665 key = key.Substring(0, key.Length-4);
1666 implicitAssemblyCache[key] = true;
1668 this.implicitAssemblyCache = implicitAssemblyCache;
1671 key = name.ToLowerInvariant();
1672 if (implicitAssemblyCache[key] != null) return;
1673 implicitAssemblyCache[key] = true;
1675 try{
1676 VsaReference assemblyReference = new VsaReference(this, name + ".dll");
1677 if (assemblyReference.Compile(false)){
1678 ArrayList implicitAssemblies = this.implicitAssemblies;
1679 if (implicitAssemblies == null) {
1680 implicitAssemblies = new ArrayList();
1681 this.implicitAssemblies = implicitAssemblies;
1683 implicitAssemblies.Add(assemblyReference.Assembly);
1685 }catch(VsaException){
1689 internal String RuntimeDirectory{
1690 get{
1691 if (this.runtimeDirectory == null){
1692 //Get the path to mscorlib.dll
1693 String s = typeof(Object).Module.FullyQualifiedName;
1694 //Remove the file part to get the directory
1695 this.runtimeDirectory = Path.GetDirectoryName(s);
1697 return this.runtimeDirectory;
1701 internal String[] LibpathList{
1702 get{
1703 if (this.libpathList == null){
1704 if (this.libpath == null)
1705 this.libpathList = new String[]{typeof(Object).Module.Assembly.Location};
1706 else
1707 this.libpathList = this.libpath.Split(new Char[] {Path.PathSeparator});
1709 return this.libpathList;
1713 internal String FindAssembly(String name){
1714 String path = name;
1715 if (Path.GetFileName(name) == name){ // just the filename, no path
1716 // Look in current directory
1717 if (File.Exists(name))
1718 path = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + name;
1719 else {
1720 // Look in COM+ runtime directory
1721 String path1 = this.RuntimeDirectory + Path.DirectorySeparatorChar + name;
1722 if (File.Exists(path1))
1723 path = path1;
1724 else{
1725 // Look on the LIBPATH
1726 String[] libpathList = this.LibpathList;
1727 foreach( String l in libpathList ){
1728 if (l.Length > 0){
1729 path1 = l + Path.DirectorySeparatorChar + name;
1730 if (File.Exists(path1)){
1731 path = path1;
1732 break;
1739 if (!File.Exists(path))
1740 return null;
1741 return path;
1744 protected override void ValidateRootMoniker(string rootMoniker){
1745 // We override this method to avoid reading the registry in a non-VSA scenario
1746 if (this.genStartupClass)
1747 base.ValidateRootMoniker(rootMoniker);
1748 else if (rootMoniker == null || rootMoniker.Length == 0)
1749 throw new VsaException(VsaError.RootMonikerInvalid);
1752 internal static bool CheckIdentifierForCLSCompliance(String name){
1753 if (name[0] == '_')
1754 return false;
1755 for (int i = 0; i < name.Length; i++){
1756 if (name[i] == '$')
1757 return false;
1759 return true;
1762 internal void CheckTypeNameForCLSCompliance(String name, String fullname, Context context){
1763 if (!this.isCLSCompliant)
1764 return;
1765 if (name[0] == '_'){
1766 context.HandleError(JSError.NonCLSCompliantType);
1767 return;
1769 if (!VsaEngine.CheckIdentifierForCLSCompliance(fullname)){
1770 context.HandleError(JSError.NonCLSCompliantType);
1771 return;
1773 if (this.typenameTable == null)
1774 this.typenameTable = new Hashtable(StringComparer.OrdinalIgnoreCase);
1775 if (this.typenameTable[fullname] == null)
1776 this.typenameTable[fullname] = fullname;
1777 else
1778 context.HandleError(JSError.NonCLSCompliantType);
1783 // The VSA spec requires that every IVsaEngine has a host property that is non-null.
1784 // Since every assembly that we generate creates an engine (see CreateEngineAndGetGlobalScope)
1785 // we must provide a default site for it.
1787 class DefaultVsaSite: BaseVsaSite{
1788 public override bool OnCompilerError(IVsaError error){
1789 // We expect only JScriptExceptions here, and we throw them to be caught by the host
1790 throw (JScriptException)error;